﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace DemoForHBQ
{
    /// <summary>
    /// 游戏类
    /// </summary>
    class Game
    {
        private const int Cols = 8;
        private const int Rows = 8;
        //此处8行8列以小方格为单元，而非五子棋中以分界线为行列
        private const int GameWidth = 1000;
        private const int GameHeight = 1000;
        public bool NextIsBlack;
        


        /// <summary>
        /// 所有块类集合
        /// </summary>
        private List<Block> Blocks { get; set; }
        //定义一个集合，其中元素为block

        public Game()
        {
            NextIsBlack = true; 
            //初始化集合
            Blocks = new List<Block>();
            for (int i = 0; i < Rows; i++)
            {
                //行遍历
                for (int j = 0; j < Cols; j++)
                {
                    //列遍历
                    Block block = new Block(new Point(i, j));
                    //把正在遍历的这个加入集合
                    Blocks.Add(block);
                }
            }
            //仍处于初始阶段
            //以下画游戏开始时棋盘上4个棋子(两黑两白成对角)
            Blocks[27].Status = BlockStatus.White;
            Blocks[36].Status = BlockStatus.White;
            Blocks[28].Status = BlockStatus.Black;
            Blocks[35].Status = BlockStatus.Black;
            //索引指示正中4格
        }

        /// <summary>
        /// 绘制当前游戏场景
        /// </summary>
        /// <param name="g">绘图句柄</param>
        /// <param name="size">游戏区域尺寸</param>
        public void Draw(Graphics g, Size size)
        {
            //指定位图大小
            Image img = new Bitmap(GameWidth, GameHeight);
            Graphics _g = Graphics.FromImage(img);
            _g.DrawImage(Properties.Resources.bg, new Rectangle(0, 0, GameWidth, GameHeight));
            //bg为非深浅区域的背景图，大小与游戏区域同

            foreach (var block in Blocks)
            {
                block.Draw(_g);
            }
            //对集合中每个block变量调用Game成员block的Draw方法

            //画背景
            Rectangle rec = new Rectangle(new Point(0, 0), size);
            g.DrawImage(img, rec);


        }

        /// <summary>
        /// 处理鼠标点击事件
        /// </summary>
        /// <param name="point"></param>
        /// <param name="size"></param>
        public void MouseDown(Point point, Size size)
        {
            //比例换算坐标
            Point newPoint = new Point(point.X * GameWidth / size.Width, point.Y * GameHeight / size.Height);

            //当前方块
            var blockNow = Blocks.FirstOrDefault(m => m.Contains(newPoint));
            if (blockNow == null || blockNow.Status != BlockStatus.Blank)
            { //若满足不在棋盘里或已被占位，返回，不进行else里操作
                return;
            }



            var colorNow = NextIsBlack ? BlockStatus.Black : BlockStatus.White; 
            var colorOther = NextIsBlack ? BlockStatus.White : BlockStatus.Black;
            //变量的值由后面的三元运算符决定（if语句的缩减）

            int countOfFood = 0;//初始吃子数为0


            //search right
            var blockRight = Blocks.Where(m => m.Point.X == blockNow.Point.X
                        && m.Point.Y > blockNow.Point.Y
                        && m.Status == colorNow).OrderBy(m => m.Point.Y).FirstOrDefault();

            if (blockRight != null)
            {
                var blocksMiddle = Blocks.Where(m => m.Point.X == blockNow.Point.X
                        && m.Point.Y > blockNow.Point.Y
                        && m.Point.Y < blockRight.Point.Y);
                if (blocksMiddle.Count() > 0 && !blocksMiddle.Any(m => m.Status != colorOther))
                {
                    countOfFood += blocksMiddle.Count();
                    foreach (var item in blocksMiddle)
                    {
                        item.Status = colorNow;
                    }
                }
            }

            //search left(已检验)
            var blockleft = Blocks.Where(m => m.Point.X == blockNow.Point.X
                          && m.Point.Y < blockNow.Point.Y
                          && m.Status == colorNow).OrderByDescending(m => m.Point.Y).FirstOrDefault();
            //按纵坐标降序排，找离待下位最近同色子
            if (blockleft != null)
            {
                //先可以找到满足条件同色子再检验中间夹子
                var blocksMiddle = Blocks.Where(m => m.Point.X == blockNow.Point.X
                        && m.Point.Y < blockNow.Point.Y
                        && m.Point.Y > blockleft.Point.Y);
                if (blocksMiddle.Count() > 0 && !blocksMiddle.Any(m => m.Status != colorOther))
                {
                    //可以吃子才有以下
                    countOfFood += blocksMiddle.Count();//统计该方向上吃子数并归入总吃子数
                    foreach (var item in blocksMiddle)
                    {
                        //改变中间夹子的状态
                        item.Status = colorNow;
                    }
                }
            }

            //search up(已检验)
            var blockup = Blocks.Where(m => m.Point.Y == blockNow.Point.Y
                          && m.Point.X < blockNow.Point.X
                          && m.Status == colorNow).OrderByDescending(m => m.Point.X).FirstOrDefault();
            //按横坐标降序排，找离待下位最近同色子
            if (blockup != null)
            {
                //先可以找到满足条件同色子再检验中间夹子
                var blocksMiddle = Blocks.Where(m => m.Point.Y == blockNow.Point.Y
                        && m.Point.X < blockNow.Point.X
                        && m.Point.X > blockup.Point.X);
                if (blocksMiddle.Count() > 0 && !blocksMiddle.Any(m => m.Status != colorOther))
                {
                    //可以吃子才有以下
                    countOfFood += blocksMiddle.Count();//统计该方向上吃子数并归入总吃子数
                    foreach (var item in blocksMiddle)
                    {
                        //改变中间夹子的状态
                        item.Status = colorNow;
                    }
                }
            }

            //search down
            var blockdown = Blocks.Where(m => m.Point.Y == blockNow.Point.Y
                          && m.Point.X > blockNow.Point.X
                          && m.Status == colorNow).OrderBy(m => m.Point.X).FirstOrDefault();
            //按横坐标升序排，找离待下位最近同色子
            if (blockdown != null)
            {
                //先可以找到满足条件同色子再检验中间夹子
                var blocksMiddle = Blocks.Where(m => m.Point.Y == blockNow.Point.Y
                        && m.Point.X > blockNow.Point.X
                        && m.Point.X < blockdown.Point.X);
                if (blocksMiddle.Count() > 0 && !blocksMiddle.Any(m => m.Status != colorOther))
                {
                    //可以吃子才有以下
                    countOfFood += blocksMiddle.Count();//统计该方向上吃子数并归入总吃子数
                    foreach (var item in blocksMiddle)
                    {
                        //改变中间夹子的状态
                        item.Status = colorNow;
                    }
                }
            }

            //search leftup(左上)
            var blockleftup = Blocks.Where(m => (m.Point.X - blockNow.Point.X) == (m.Point.Y - blockNow.Point.Y)
                          && m.Point.X < blockNow.Point.X
                          && m.Point.Y < blockNow.Point.Y
                          && m.Status == colorNow).OrderByDescending(m => m.Point.X).FirstOrDefault();
            //斜着方向的吃子需要坐标变换，以待下棋位为原点
            //按横坐标降排，找离待下位最近同色子
            if (blockleftup != null)
            {
                //先找到满足条件同色子再检验中间夹子
                var blocksMiddle = Blocks.Where(m => (m.Point.X - blockNow.Point.X) == (m.Point.Y - blockNow.Point.Y)
                        && m.Point.X < blockNow.Point.X
                        && m.Point.Y < blockNow.Point.Y
                        && m.Point.X > blockleftup.Point.X
                        && m.Point.Y > blockleftup.Point.Y);
                if (blocksMiddle.Count() > 0 && !blocksMiddle.Any(m => m.Status != colorOther))
                {
                    //可以吃子才有以下
                    countOfFood += blocksMiddle.Count();//统计该方向上吃子数并归入总吃子数
                    foreach (var item in blocksMiddle)
                    {
                        //改变中间夹子的状态
                        item.Status = colorNow;
                    }
                }
            }

            //search rightup(右上)
            var blockrightup = Blocks.Where(m => (m.Point.X - blockNow.Point.X) + (m.Point.Y - blockNow.Point.Y) == 0
                           && m.Point.X < blockNow.Point.X
                           && m.Point.Y > blockNow.Point.Y
                           && m.Status == colorNow).OrderBy(m => m.Point.Y).FirstOrDefault();
            //按纵坐标升排，找离待下位最近同色子
            if (blockrightup != null)
            {
                //先找到满足条件同色子再检验中间夹子
                var blocksMiddle = Blocks.Where(m => (m.Point.X - blockNow.Point.X) + (m.Point.Y - blockNow.Point.Y) == 0
                        && m.Point.X < blockNow.Point.X
                        && m.Point.Y > blockNow.Point.Y
                        && m.Point.X > blockrightup.Point.X
                        && m.Point.Y < blockrightup.Point.Y);
                if (blocksMiddle.Count() > 0 && !blocksMiddle.Any(m => m.Status != colorOther))
                {
                    //可以吃子才有以下
                    countOfFood += blocksMiddle.Count();//统计该方向上吃子数并归入总吃子数
                    foreach (var item in blocksMiddle)
                    {
                        //改变中间夹子的状态
                        item.Status = colorNow;
                    }
                }
            }

            //search leftdown(左下)
            var blockleftdown = Blocks.Where(m => (m.Point.X - blockNow.Point.X) + (m.Point.Y - blockNow.Point.Y) == 0
                           && m.Point.X > blockNow.Point.X
                           && m.Point.Y < blockNow.Point.Y
                           && m.Status == colorNow).OrderBy(m => m.Point.Y).FirstOrDefault();
            //按纵坐标升排，找离待下位最近同色子
            if (blockleftdown != null)
            {
                //先找到满足条件同色子再检验中间夹子
                var blocksMiddle = Blocks.Where(m => (m.Point.X - blockNow.Point.X) + (m.Point.Y - blockNow.Point.Y) == 0
                        && m.Point.X > blockNow.Point.X
                        && m.Point.Y < blockNow.Point.Y
                        && m.Point.X < blockleftdown.Point.X
                        && m.Point.Y > blockleftdown.Point.Y);
                if (blocksMiddle.Count() > 0 && !blocksMiddle.Any(m => m.Status != colorOther))
                {
                    //可以吃子才有以下
                    countOfFood += blocksMiddle.Count();//统计该方向上吃子数并归入总吃子数
                    foreach (var item in blocksMiddle)
                    {
                        //改变中间夹子的状态
                        item.Status = colorNow;
                    }
                }
            }

            //search rightdown(右下)
            var blockrightdown = Blocks.Where(m => (m.Point.X - blockNow.Point.X) == (m.Point.Y - blockNow.Point.Y)
                           && m.Point.X > blockNow.Point.X
                           && m.Point.Y > blockNow.Point.Y
                           && m.Status == colorNow).OrderBy(m => m.Point.Y).FirstOrDefault();
            //按纵坐标升排，找离待下位最近同色子
            if (blockrightdown != null)
            {
                //先找到满足条件同色子再检验中间夹子
                var blocksMiddle = Blocks.Where(m => (m.Point.X - blockNow.Point.X) == (m.Point.Y - blockNow.Point.Y)
                        && m.Point.X > blockNow.Point.X
                        && m.Point.Y > blockNow.Point.Y
                        && m.Point.X < blockrightdown.Point.X
                        && m.Point.Y < blockrightdown.Point.Y);
                if (blocksMiddle.Count() > 0 && !blocksMiddle.Any(m => m.Status != colorOther))
                {
                    //可以吃子才有以下
                    countOfFood += blocksMiddle.Count();//统计该方向上吃子数并归入总吃子数
                    foreach (var item in blocksMiddle)
                    {
                        //改变中间夹子的状态
                        item.Status = colorNow;
                    }
                }
            }

            if (countOfFood > 0)
            {
                //先判断上述吃子数非零，若满足，翻棋
                blockNow.MouseDown(NextIsBlack);
                //切换黑白
                NextIsBlack = !NextIsBlack;  
            }
        }

       /// <summary>
       /// 判断输赢
       /// </summary>
       /// <returns></returns>
        public int IsGameOver()
        {
            //定义目前棋盘上的黑子白子总数
            var Num_Black = Blocks.Count(m => m.Status == BlockStatus.Black);
            var Num_White = Blocks.Count(m => m.Status == BlockStatus.White);

            if (Num_Black + Num_White == 64)
            {
                //棋盘已铺满
                if (Num_Black > Num_White)//白棋少
                    return 0;
                else if (Num_Black < Num_White)//黑棋少
                        return 1;
            }
            return 2;
        }
    }
}
